package com.example.ccmusic

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Intent
import android.media.AudioAttributes
import android.media.MediaPlayer
import android.net.Uri
import android.os.Handler
import android.os.HandlerThread
import android.os.IBinder
import android.os.Message
import android.util.Log
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat

/**
 * 歌曲数据存在activity
 * service启动通知
 * 通知中的操作通过广播通知activity
 * activity更新数据并通知service播放
 * 那么，使用bindService还是startService？
 * activity通过startService可以传递数据到service
 * service只需要启动通知，根据activity的数据播放音乐，不需要传递数据给activity
 * 对音乐的操作都在通知
 *
 * 播放音乐：
 * activity -> service -> 播放，更新通知
 * 通知 -> activity and service -> 更新ui
 *
 * remoteViews 貌似不能保存起来，需要每次都重新发送通知
 *
 */
private const val TAG = "MusicService"
private const val CHANNEL_ID: String = "ccmusic"

class MusicService : Service() {
    private var currentMusic: Music? = null
    private var workerHandler: Handler? = null
    private var mediaPlayer: MediaPlayer? = null
    private val audioAttributes: AudioAttributes = AudioAttributes.Builder()
        .setFlags(AudioAttributes.CONTENT_TYPE_MUSIC or AudioAttributes.USAGE_MEDIA)
        .build()

    override fun onCreate() {
        super.onCreate()
        Log.d(TAG, "onCreate")
        val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        val channel =
            NotificationChannel(CHANNEL_ID, "music", NotificationManager.IMPORTANCE_DEFAULT)
        channel.setSound(null, null)
        notificationManager.createNotificationChannel(channel)
        prepareHandler()
    }

    private fun prepareHandler() {
        val workerThread = HandlerThread("work-thread")
        workerThread.start()
        workerHandler = object : Handler(workerThread.looper) {
            override fun handleMessage(msg: Message) {
                when (msg.what) {
                    Constants.COMMAND_CHANGE_MUSIC -> {
                        val intent = msg.obj as Intent
                        val music =
                            IntentUtils.getParcelableExtra(intent, Constants.EXTRA_MUSIC) as Music?
                        music?.let {
                            currentMusic = it
                            // FIXME: 失效了，是因为在子线程吗?
                            val notification = createNotification()
                            startForeground(10001, notification)
                            changeMusic()
                        }
                    }
                }
            }
        }
    }

    private fun changeMusic() {
        // 1.检查mediaPlayer
        if (mediaPlayer == null) {
            mediaPlayer = MediaPlayer()
        } else {
            mediaPlayer?.reset()
        }
        // 2. 播放
        currentMusic?.let { music ->
            val uri = Uri.parse(music.path)
            mediaPlayer?.apply {
                setAudioAttributes(audioAttributes)
                setDataSource(applicationContext, uri)
                prepare()
                start()
            }
        }
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        val cmd = IntentUtils.getIntExtra(intent, Constants.EXTRA_COMMAND, -1)
        Log.d(TAG, "onStartCommand: command = $cmd")
        if (cmd != -1) {
            workerHandler?.let {
                val message = it.obtainMessage().apply {
                    what = cmd
                    obj = intent
                }
                it.sendMessage(message)
            }
        }
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d(TAG, "onDestroy")
        mediaPlayer?.release()
    }

    private fun createNotification(): Notification {
        Log.d(TAG, "createNotification")
        return NotificationCompat.Builder(this, CHANNEL_ID)
            .setSmallIcon(R.mipmap.default_icon)
            .setWhen(System.currentTimeMillis())
            .setContentTitle("music")
            .setCustomBigContentView(getContentView())
            .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
            .build()
    }

    private fun getContentView(): RemoteViews {
        Log.d(TAG, "getContentView")
        val remoteViews = RemoteViews(packageName, R.layout.notification_content)
        remoteViews.setTextViewText(R.id.music_name, currentMusic?.title)
        remoteViews.setTextViewText(R.id.music_author, currentMusic?.artist)
        // remoteViews.setImageViewUri(R.id.music_icon, )
        remoteViews.setTextViewText(R.id.music_progress, "00:00")
        remoteViews.setTextViewText(R.id.music_duration, currentMusic?.duration.toString())
        return remoteViews
    }
}